#ifndef _HTTP_H
#define _HTTP_H

#define off64_t _off64_t	// fix io.h
#include <io.h>
#include <ctime>
#include <iomanip>	// for setfill and setw
#include <sys/stat.h>
#include "threading.h"
#include "confparser.h"
#define stat _stati64

bool caseCompare(std::string,std::string);
void Handle(LPVOID);
class Headers {
	public:
		typedef std::unordered_map<std::string,std::string>::iterator Iterator;
		bool GetHeader(std::string,std::string *);
		void SetHeader(std::string,std::string);
		void DelHeader(std::string);
		void Clear();
		Iterator Begin();
		Iterator End();
	private:
		std::unordered_map<std::string,std::string> headers;
		std::string Capitalize(std::string);
};
class Request {
	public:
		int protocol;
		Headers headers;
		std::string method,request_uri,host,
		       rewrited_path,path,query_string,
		       root,file_path,request_line;
		Request(THREAD_DATA *);
		void Init();
	private:
		THREAD_DATA *td;
};
class Response {
	public:
		int protocol,status,bytes_sent;
		bool ok;
		std::string message;
		clock_t ts;
		Headers headers;
		bool alive,error;
		Response(THREAD_DATA *);
		void Init();
		void SetStatus(int,std::string);
		void SetStatus(int);
		void SendHeaders();
		void Write(const char *,int);
		void Write(std::string);
		void Flush(const char *,int);
		void Flush();
		void End();
	private:
		bool headers_sent,chunked;
		THREAD_DATA *td;
		std::stringstream ss;
};
class HTTPHandler {
	public:
		HTTPHandler(THREAD_DATA *);
		~HTTPHandler();
		bool HandleOne();
		void SendError(int,std::string);
		void SendError(int);
	private:
		time_t timestamp;
		clock_t clock_start;
		THREAD_DATA *td;
		Request *req;
		Response *res;
		HostItem *hconf;
		std::stringstream ss;
		struct stat st;
		int ReadData(std::stringstream *);
		int ReadLine(std::stringstream *,std::string *);
		int ParseRequest();
		bool IsOuterURL(std::string);
		int ParseURL(std::string);
		int GetRealPath();
		void ListDir();
		void SendFile();
		MIMEType *GuessType();
		bool CheckModified();
		void DoGET();
		void HandleFile();
		void HandleURL(std::string);
		int Hex2Dec(std::string);
		std::string Unquote(std::string);
		std::string UTF8TOACP(std::string);
		void Redirect(std::string,int);
		void Redirect(std::string);
		void WriteHTMLHeader(std::string);
		void WriteHTMLFooter(std::string);
};
class HTTPServer:public ThreadedServer {
	public:
		MIMEMap *pmime;
		ServerItem *conf;
		HTTPServer(ServerItem *);
		void _StartServer();
	private:
		typedef struct {
			HTTPServer *server;
		} HTTP_SERVER_DATA;
		static unsigned __stdcall _StartServerThread(LPVOID);
};

#endif
